package redis.clients.jedis.commands;

import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.jedis.BitPosParams;
import redis.clients.jedis.StreamConsumersInfo;
import redis.clients.jedis.StreamEntryID;
import redis.clients.jedis.GeoCoordinate;
import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.ListPosition;
import redis.clients.jedis.StreamGroupInfo;
import redis.clients.jedis.StreamInfo;
import redis.clients.jedis.StreamPendingEntry;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import redis.clients.jedis.SortingParams;
import redis.clients.jedis.StreamEntry;
import redis.clients.jedis.StreamPendingSummary;
import redis.clients.jedis.Tuple;
import redis.clients.jedis.params.GeoAddParams;
import redis.clients.jedis.params.GeoRadiusParam;
import redis.clients.jedis.params.GetExParams;
import redis.clients.jedis.params.RestoreParams;
import redis.clients.jedis.params.SetParams;
import redis.clients.jedis.params.StrAlgoLCSParams;
import redis.clients.jedis.params.XAddParams;
import redis.clients.jedis.params.XAutoClaimParams;
import redis.clients.jedis.params.XClaimParams;
import redis.clients.jedis.params.XPendingParams;
import redis.clients.jedis.params.XTrimParams;
import redis.clients.jedis.params.ZAddParams;
import redis.clients.jedis.params.ZIncrByParams;
import redis.clients.jedis.params.LPosParams;
import redis.clients.jedis.resps.KeyedListElement;
import redis.clients.jedis.resps.LCSMatchResult;

/**
 * 分片和非分片Jedis的通用接口
 * <p>
 * JedisCommands是Jedis提供的一个接口，它定义了Redis命令的基本操作。
 * 通过实现该接口，可以自定义一些Redis命令的操作。
 */
public interface JedisCommands {


/*
-----------------------------------------------String-------------------------------------------------
*/

    /**
     * 设置指定key的值
     */
    String set(String key, String value);

    String set(String key, String value, SetParams params);

    /**
     * 用于修改字符串中指定位置的内容
     */
    Long setrange(String key, long offset, String value);


    /**
     * 获取指定key的值
     */
    String get(String key);

    /**
     * 用于获取字符串中指定范围内的子串
     */
    String getrange(String key, long startOffset, long endOffset);


    /**
     * 用于获取并删除指定 key 的值
     */
    String getDel(String key);


    /**
     * 用于获取键值对的值并设置过期时间
     */
    String getEx(String key, GetExParams params);

    /**
     * 判断指定key是否存在
     */
    Boolean exists(String key);


    /**
     * 获取指定 key 的值的类型
     */
    String type(String key);


    /**
     * 用于序列化给定 key 的值的命令。它将 key 的值转换为字节流，
     * 并返回一个表示该序列化值的字符串。
     * 这个命令主要用于备份和复制操作，以及实现某些高级功能
     */
    byte[] dump(String key);


    /**
     * 用于将已序列化的值恢复为 Redis key 的命令。
     * 它通常与 dump 命令结合使用，以实现数据的备份和恢复功能
     */
    String restore(String key, long ttl, byte[] serializedValue);

    String restore(String key, long ttl, byte[] serializedValue, RestoreParams params);


    /**
     * 移除给定 key 的过期时间，使其成为永久有效
     */
    Long persist(String key);

    /**
     * 为指定的 key 设置过期时间（单位：秒）
     */
    Long expire(String key, long seconds);

    /**
     * 为指定的 key 设置过期时间（单位：毫秒）
     */
    Long pexpire(String key, long milliseconds);


    /**
     * 用于设置 key 的过期时间。与 expire 命令不同，
     * expireAt 接受的时间参数是 UNIX 时间戳（即从 1970 年 1 月 1 日 00:00:00 UTC 到现在的
     * <p>
     * 秒数
     */
    Long expireAt(String key, long unixTime);

    /**
     * 用于设置 key 的过期时间。与 expire 命令不同，
     * expireAt 接受的时间参数是 UNIX 时间戳（即从 1970 年 1 月 1 日 00:00:00 UTC 到现在的
     * <p>
     * 毫秒数
     */
    Long pexpireAt(String key, long millisecondsTimestamp);

    /**
     * 获取指定key的剩余生存时间 单位:秒
     */
    Long ttl(String key);

    /**
     * 获取指定key的剩余生存时间 单位:毫秒
     */
    Long pttl(String key);

    /**
     * 用于更新 key 的过期时间。如果 key 不存在，则不会进行任何操作
     */
    Long touch(String key);

    Boolean setbit(String key, long offset, boolean value);

    /**
     * @deprecated Use {@link #setbit(java.lang.String, long, boolean)}.
     */
    @Deprecated
    Boolean setbit(String key, long offset, String value);

    Boolean getbit(String key, long offset);


    String getSet(String key, String value);

    Long setnx(String key, String value);

    /**
     * @deprecated Use {@link #setex(java.lang.String, long, java.lang.String)}.
     */
    @Deprecated
    default String setex(String key, int seconds, String value) {
        return setex(key, (long) seconds, value);
    }

    String setex(String key, long seconds, String value);

    String psetex(String key, long milliseconds, String value);

    Long decrBy(String key, long decrement);

    Long decr(String key);

    Long incrBy(String key, long increment);

    Double incrByFloat(String key, double increment);

    Long incr(String key);

    Long append(String key, String value);

    String substr(String key, int start, int end);




/*
-----------------------------------------------hash-------------------------------------------------
*/

    /**
     * 设置哈希表中指定field的值
     */
    Long hset(String key, String field, String value);

    Long hset(String key, Map<String, String> hash);


    /**
     * 获取哈希表中指定field的值
     */
    String hget(String key, String field);


    /**
     * 删除哈希表中指定的一个或多个field
     */
    Long hdel(String key, String... field);


    /**
     * 判断哈希表中指定field是否存在
     */
    Boolean hexists(String key, String field);


    Long hsetnx(String key, String field, String value);

    String hmset(String key, Map<String, String> hash);

    List<String> hmget(String key, String... fields);

    Long hincrBy(String key, String field, long value);

    Double hincrByFloat(String key, String field, double value);


    Long hlen(String key);

    Set<String> hkeys(String key);

    List<String> hvals(String key);

    Map<String, String> hgetAll(String key);

    String hrandfield(String key);

    List<String> hrandfield(String key, long count);

    Map<String, String> hrandfieldWithValues(String key, long count);



/*
-----------------------------------------------hash-------------------------------------------------
*/

    /**
     * 将一个或多个值插入到列表尾部
     */
    Long rpush(String key, String... string);

    /**
     * 将一个或多个值插入到列表头部
     */
    Long lpush(String key, String... string);


    /**
     * 根据参数 count，移除列表中与参数 value相等的元素。
     */
    Long lrem(String key, long count, String value);

    /**
     * 根据起始位置和结束位置修剪列表。
     */
    String ltrim(String key, long start, long stop);


    /**
     * 移除并返回列表头部的元素；
     */
    String lpop(String key);

    /**
     * 获取列表指定范围的元素
     */
    List<String> lrange(String key, long start, long stop);

    /**
     * 获取列表的长度
     */
    Long llen(String key);


    String lindex(String key, long index);

    String lset(String key, long index, String value);


    List<String> lpop(String key, int count);

    Long lpos(String key, String element);

    Long lpos(String key, String element, LPosParams params);

    List<Long> lpos(String key, String element, LPosParams params, long count);

    String rpop(String key);

    List<String> rpop(String key, int count);



/*
-----------------------------------------------set-------------------------------------------------
*/

    /**
     * 向指定 key 的 set 中添加一个或多个 member。
     * 如果某个 member 已经存在于 set 中，则会被忽略。返回添加成功的 member 的数量。
     */
    Long sadd(String key, String... member);


    /**
     * 获取指定 key 的 set 中所有的 member，以列表的形式返回
     */
    Set<String> smembers(String key);

    /**
     * 从指定 key 的 set 中随机获取 count 个不重复的 member，以列表的形式返回
     */
    List<String> srandmember(String key, int count);

    /**
     * 获取指定 key 的 set 中 member 的数量
     */
    Long scard(String key);

    /**
     * 判断指定 member 是否存在于指定 key 的 set 中。
     * 如果存在，则返回 true
     * 否则返回 false
     */
    Boolean sismember(String key, String member);


    /**
     * 从指定 key 的 set 中移除一个或多个 member。
     * 如果某个 member 不存在于 set 中，则不进行任何操作。返回移除成功的 member 的数量。
     */
    Long srem(String key, String... member);


    /**
     *
     */
    String spop(String key);

    /**
     * 从指定 key 的 set 中随机移除并返回 count 个不重复的 member，以列表的形式返回。
     * 如果 count > set 的大小，则移除所有 member
     */
    Set<String> spop(String key, long count);


    List<Boolean> smismember(String key, String... members);

    String srandmember(String key);


    Long strlen(String key);







/*
-----------------------------------------------Zset-------------------------------------------------
*/

    /**
     * 添加一个 member，每个 member 都带有一个 score（分值）
     * 如果某个 member 已经存在于 zset 中，则更新其 score。返回添加成功的 member 的数量。
     */
    Long zadd(String key, double score, String member);

    Long zadd(String key, double score, String member, ZAddParams params);

    /**
     * 添加一个或多个 member，每个 member 都带有一个 score（分值）。
     * 如果某个 member 已经存在于 zset 中，则更新其 score。返回添加成功的 member 的数量。
     */
    Long zadd(String key, Map<String, Double> scoreMembers);

    Long zadd(String key, Map<String, Double> scoreMembers, ZAddParams params);

    Double zaddIncr(String key, double score, String member, ZAddParams params);

    /**
     * 获取指定 key 的 zset 中指定范围的 member，按 score 从小到大排序。
     * 返回一个列表，包含指定范围内的所有 member。
     */
    Set<String> zrange(String key, long start, long stop);

    /**
     * 获取指定 key 的 zset 中指定范围的 member，按 score 从大到小排序。
     * 返回一个列表，包含指定范围内的所有 member
     */
    Set<String> zrevrange(String key, long start, long stop);

    /**
     * 获取指定 member 在指定 key 的 zset 中的排名（按照 score 从小到大排序）。
     * 如果 member 不存在于 zset 中，则返回 null。
     */
    Long zrank(String key, String member);

    /**
     * 获取指定 member 在指定 key 的 zset 中的排名（按照 score 从大到小排序）。
     * 如果 member 不存在于 zset 中，则返回 null。
     */
    Long zrevrank(String key, String member);

    /**
     * 获取指定 key 的 zset 中 member 的数量
     */
    Long zcard(String key);

    /**
     * 获取指定 member 在指定 key 的 zset 中的 score。
     * 如果 member 不存在于 zset 中，则返回 null。
     */
    Double zscore(String key, String member);

    /**
     * 获取有序集合中指定成员的分数。
     * 它返回指定成员的分数，如果成员不存在则返回null。
     */
    List<Double> zmscore(String key, String... members);



    /**
     * 移除一个或多个 member
     * 如果某个 member 不存在于 zset 中，则不进行任何操作。返回移除成功的 member 的数量。
     */
    Long zrem(String key, String... members);

    /**
     * 将指定 member 的 score 增加指定的值，然后返回增加后的新 score。
     * 如果 member 不存在于 zset 中，则先将其添加到 zset 中再执行操作
     */
    Double zincrby(String key, double increment, String member);

    Double zincrby(String key, double increment, String member, ZIncrByParams params);


    /**
     * 用于获取有序集合中指定范围内的元素及其分数。（按照 score 从小到大排序）。
     * 它返回一个包含元素和分数的列表，其中每个元素是一个包含两个元素的数组，
     * 第一个元素是成员，第二个元素是分数。
     */
    Set<Tuple> zrangeWithScores(String key, long start, long stop);

    /**
     * 用于获取有序集合中指定范围内的元素及其分数。（按照 score 从大到小排序）。
     * 它返回一个包含元素和分数的列表，其中每个元素是一个包含两个元素的数组，
     * 第一个元素是成员，第二个元素是分数。
     */
    Set<Tuple> zrevrangeWithScores(String key, long start, long stop);

    /**
     * 用于从有序集合中随机获取指定数量的元素。
     * 它返回一个包含随机元素的列表，元素的顺序是随机的。
     */
    String zrandmember(String key);

    /**
     * 用于从有序集合中随机获取指定数量的元素。
     * 它返回一个包含随机元素的列表，元素的顺序是随机的。
     */
    Set<String> zrandmember(String key, long count);

    /**
     * 用于从有序集合中随机获取指定数量的元素，并返回每个元素的分数。
     * 它返回一个包含随机元素及其分数的列表，元素的顺序是随机的
     */
    Set<Tuple> zrandmemberWithScores(String key, long count);


    /**
     * 移除并返回具有最大分数的成员。
     * 它返回一个包含被移除成员及其分数的列表，如果集合为空则返回null
     */
    Tuple zpopmax(String key);

    Set<Tuple> zpopmax(String key, int count);

    /**
     * 移除并返回具有最小分数的成员。
     * 它返回一个包含被移除成员及其分数的列表，如果集合为空则返回null
     */
    Tuple zpopmin(String key);

    Set<Tuple> zpopmin(String key, int count);


    /**
     * 集合中的元素进行排序。它返回一个包含排序后元素的列表
     */
    List<String> sort(String key);

    List<String> sort(String key, SortingParams sortingParameters);

    Long zcount(String key, double min, double max);

    Long zcount(String key, String min, String max);

    Set<String> zrangeByScore(String key, double min, double max);

    Set<String> zrangeByScore(String key, String min, String max);

    Set<String> zrevrangeByScore(String key, double max, double min);

    Set<String> zrangeByScore(String key, double min, double max, int offset, int count);

    Set<String> zrevrangeByScore(String key, String max, String min);

    Set<String> zrangeByScore(String key, String min, String max, int offset, int count);

    Set<String> zrevrangeByScore(String key, double max, double min, int offset, int count);

    Set<Tuple> zrangeByScoreWithScores(String key, double min, double max);

    Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min);

    Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset, int count);

    Set<String> zrevrangeByScore(String key, String max, String min, int offset, int count);

    Set<Tuple> zrangeByScoreWithScores(String key, String min, String max);

    Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min);

    Set<Tuple> zrangeByScoreWithScores(String key, String min, String max, int offset, int count);

    Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count);

    Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count);

    Long zremrangeByRank(String key, long start, long stop);

    Long zremrangeByScore(String key, double min, double max);

    Long zremrangeByScore(String key, String min, String max);

    Long zlexcount(String key, String min, String max);

    Set<String> zrangeByLex(String key, String min, String max);

    Set<String> zrangeByLex(String key, String min, String max, int offset, int count);

    Set<String> zrevrangeByLex(String key, String max, String min);

    Set<String> zrevrangeByLex(String key, String max, String min, int offset, int count);

    Long zremrangeByLex(String key, String min, String max);

    Long linsert(String key, ListPosition where, String pivot, String value);

    Long lpushx(String key, String... string);

    Long rpushx(String key, String... string);

    List<String> blpop(int timeout, String key);

    KeyedListElement blpop(double timeout, String key);

    List<String> brpop(int timeout, String key);

    KeyedListElement brpop(double timeout, String key);


    /**
     * 删除指定key
     */
    Long del(String key);

    Long unlink(String key);

    String echo(String string);

    Long move(String key, int dbIndex);

    Long bitcount(String key);

    Long bitcount(String key, long start, long end);

    Long bitpos(String key, boolean value);

    Long bitpos(String key, boolean value, BitPosParams params);

    ScanResult<Map.Entry<String, String>> hscan(String key, String cursor);

    ScanResult<Map.Entry<String, String>> hscan(String key, String cursor, ScanParams params);

    ScanResult<String> sscan(String key, String cursor);

    ScanResult<Tuple> zscan(String key, String cursor);

    ScanResult<Tuple> zscan(String key, String cursor, ScanParams params);

    ScanResult<String> sscan(String key, String cursor, ScanParams params);

    Long pfadd(String key, String... elements);

    long pfcount(String key);

    // Geo Commands

    Long geoadd(String key, double longitude, double latitude, String member);

    Long geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap);

    Long geoadd(String key, GeoAddParams params, Map<String, GeoCoordinate> memberCoordinateMap);

    Double geodist(String key, String member1, String member2);

    Double geodist(String key, String member1, String member2, GeoUnit unit);

    List<String> geohash(String key, String... members);

    List<GeoCoordinate> geopos(String key, String... members);

    List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius,
                                      GeoUnit unit);

    List<GeoRadiusResponse> georadiusReadonly(String key, double longitude, double latitude,
                                              double radius, GeoUnit unit);

    List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius,
                                      GeoUnit unit, GeoRadiusParam param);

    List<GeoRadiusResponse> georadiusReadonly(String key, double longitude, double latitude,
                                              double radius, GeoUnit unit, GeoRadiusParam param);

    List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit);

    List<GeoRadiusResponse> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit);

    List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit,
                                              GeoRadiusParam param);

    List<GeoRadiusResponse> georadiusByMemberReadonly(String key, String member, double radius,
                                                      GeoUnit unit, GeoRadiusParam param);

    /**
     * Executes BITFIELD Redis command
     *
     * @param key
     * @param arguments
     */
    List<Long> bitfield(String key, String... arguments);

    List<Long> bitfieldReadonly(String key, String... arguments);

    /**
     * Used for HSTRLEN Redis command
     *
     * @param key
     * @param field
     * @return length of the value for key
     */
    Long hstrlen(String key, String field);

    /**
     * XADD key ID field string [field string ...]
     *
     * @param key
     * @param id
     * @param hash
     * @return the ID of the added entry
     */
    StreamEntryID xadd(String key, StreamEntryID id, Map<String, String> hash);

    /**
     * XADD key MAXLEN ~ LEN ID field string [field string ...]
     *
     * @param key
     * @param id
     * @param hash
     * @param maxLen
     * @param approximateLength
     */
    StreamEntryID xadd(String key, StreamEntryID id, Map<String, String> hash, long maxLen, boolean approximateLength);

    /**
     * XADD key [NOMKSTREAM] [MAXLEN|MINID [=|~] threshold [LIMIT count]] *|ID field value [field value ...]
     *
     * @param key
     * @param hash
     * @param params
     */
    StreamEntryID xadd(String key, Map<String, String> hash, XAddParams params);

    /**
     * XLEN key
     *
     * @param key
     */
    Long xlen(String key);

    /**
     * XRANGE key start end
     * <p>
     * WARNING: Sending untyped null for both start and end would raise compilation error. Casting the
     * nulls to {@link StreamEntryID} would resolve the error.
     *
     * @param key
     * @param start minimum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate minimum ID possible in the stream
     * @param end   maximum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate maximum ID possible in the stream
     * @return The entries with IDs matching the specified range.
     */
    List<StreamEntry> xrange(String key, StreamEntryID start, StreamEntryID end);

    /**
     * XRANGE key start end COUNT count
     * <p>
     * WARNING: Sending untyped null for both start and end would raise compilation error. Casting the
     * nulls to {@link StreamEntryID} would resolve the error.
     *
     * @param key
     * @param start minimum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate minimum ID possible in the stream
     * @param end   maximum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate maximum ID possible in the stream
     * @param count maximum number of entries returned
     * @return The entries with IDs matching the specified range.
     */
    List<StreamEntry> xrange(String key, StreamEntryID start, StreamEntryID end, int count);

    /**
     * XREVRANGE key end start
     * <p>
     * WARNING: Sending untyped null for both start and end would raise compilation error. Casting the
     * nulls to {@link StreamEntryID} would resolve the error.
     *
     * @param key
     * @param start minimum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate minimum ID possible in the stream
     * @param end   maximum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate maximum ID possible in the stream
     * @return the entries with IDs matching the specified range, from the higher ID to the lower ID matching.
     */
    List<StreamEntry> xrevrange(String key, StreamEntryID end, StreamEntryID start);

    /**
     * XREVRANGE key end start COUNT count
     * <p>
     * WARNING: Sending untyped null for both start and end would raise compilation error. Casting the
     * nulls to {@link StreamEntryID} would resolve the error.
     *
     * @param key
     * @param start minimum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate minimum ID possible in the stream
     * @param end   maximum {@link StreamEntryID} for the retrieved range, passing <code>null</code> will indicate maximum ID possible in the stream
     * @param count The entries with IDs matching the specified range.
     * @return the entries with IDs matching the specified range, from the higher ID to the lower ID matching.
     */
    List<StreamEntry> xrevrange(String key, StreamEntryID end, StreamEntryID start, int count);

    /**
     * XACK key group ID [ID ...]
     *
     * @param key
     * @param group
     * @param ids
     */
    long xack(String key, String group, StreamEntryID... ids);

    /**
     * XGROUP CREATE <key> <groupname> <id or $>
     *
     * @param key
     * @param groupname
     * @param id
     * @param makeStream
     */
    String xgroupCreate(String key, String groupname, StreamEntryID id, boolean makeStream);

    /**
     * XGROUP SETID <key> <groupname> <id or $>
     *
     * @param key
     * @param groupname
     * @param id
     */
    String xgroupSetID(String key, String groupname, StreamEntryID id);

    /**
     * XGROUP DESTROY <key> <groupname>
     *
     * @param key
     * @param groupname
     */
    long xgroupDestroy(String key, String groupname);

    /**
     * XGROUP DELCONSUMER <key> <groupname> <consumername>
     *
     * @param key
     * @param groupname
     * @param consumername
     */
    Long xgroupDelConsumer(String key, String groupname, String consumername);

    /**
     * XPENDING key group
     *
     * @param key
     * @param groupname
     */
    StreamPendingSummary xpending(String key, String groupname);

    /**
     * XPENDING key group [start end count] [consumer]
     *
     * @param key
     * @param groupname
     * @param start
     * @param end
     * @param count
     * @param consumername
     */
    List<StreamPendingEntry> xpending(String key, String groupname, StreamEntryID start,
                                      StreamEntryID end, int count, String consumername);

    /**
     * XPENDING key group [[IDLE min-idle-time] start end count [consumer]]
     *
     * @param key
     * @param groupname
     * @param params
     */
    List<StreamPendingEntry> xpending(String key, String groupname, XPendingParams params);

    /**
     * XDEL key ID [ID ...]
     *
     * @param key
     * @param ids
     */
    long xdel(String key, StreamEntryID... ids);

    /**
     * XTRIM key MAXLEN [~] count
     *
     * @param key
     * @param maxLen
     * @param approximate
     */
    long xtrim(String key, long maxLen, boolean approximate);

    /**
     * XTRIM key MAXLEN|MINID [=|~] threshold [LIMIT count]
     *
     * @param key
     * @param params
     */
    long xtrim(String key, XTrimParams params);

    /**
     * XCLAIM <key> <group> <consumer> <min-idle-time> <ID-1> <ID-2>
     * [IDLE <milliseconds>] [TIME <mstime>] [RETRYCOUNT <count>]
     * [FORCE] [JUSTID]
     */
    List<StreamEntry> xclaim(String key, String group, String consumername, long minIdleTime,
                             long newIdleTime, int retries, boolean force, StreamEntryID... ids);

    /**
     * XCLAIM <key> <group> <consumer> <min-idle-time> <ID-1> ... <ID-N>
     * [IDLE <milliseconds>] [TIME <mstime>] [RETRYCOUNT <count>]
     * [FORCE]
     */
    List<StreamEntry> xclaim(String key, String group, String consumername, long minIdleTime,
                             XClaimParams params, StreamEntryID... ids);

    /**
     * XCLAIM <key> <group> <consumer> <min-idle-time> <ID-1> ... <ID-N>
     * [IDLE <milliseconds>] [TIME <mstime>] [RETRYCOUNT <count>]
     * [FORCE] JUSTID
     */
    List<StreamEntryID> xclaimJustId(String key, String group, String consumername, long minIdleTime,
                                     XClaimParams params, StreamEntryID... ids);

    /**
     * XAUTOCLAIM key group consumer min-idle-time start [COUNT count]
     *
     * @param key          Stream Key
     * @param group        Consumer Group
     * @param consumerName Consumer name to transfer the auto claimed entries
     * @param minIdleTime  Entries pending more than minIdleTime will be transferred ownership
     * @param start        {@link StreamEntryID} - Entries >= start will be transferred ownership, passing <code>null</code> will indicate '-'
     * @param params       {@link XAutoClaimParams}
     */
    Map.Entry<StreamEntryID, List<StreamEntry>> xautoclaim(String key, String group, String consumerName,
                                                           long minIdleTime, StreamEntryID start, XAutoClaimParams params);

    /**
     * XAUTOCLAIM key group consumer min-idle-time start [COUNT count] JUSTID
     *
     * @param key          Stream Key
     * @param group        Consumer Group
     * @param consumerName Consumer name to transfer the auto claimed entries
     * @param minIdleTime  Entries pending more than minIdleTime will be transferred ownership
     * @param start        {@link StreamEntryID} - Entries >= start will be transferred ownership, passing <code>null</code> will indicate '-'
     * @param params       {@link XAutoClaimParams}
     */
    Map.Entry<StreamEntryID, List<StreamEntryID>> xautoclaimJustId(String key, String group, String consumerName,
                                                                   long minIdleTime, StreamEntryID start, XAutoClaimParams params);

    /**
     * Introspection command used in order to retrieve different information about the stream
     *
     * @param key Stream name
     * @return {@link StreamInfo} that contains information about the stream
     */
    StreamInfo xinfoStream(String key);

    /**
     * Introspection command used in order to retrieve different information about groups in the stream
     *
     * @param key Stream name
     * @return List of {@link StreamGroupInfo} containing information about groups
     */
    List<StreamGroupInfo> xinfoGroup(String key);

    /**
     * Introspection command used in order to retrieve different information about consumers in the group
     *
     * @param key   Stream name
     * @param group Group name
     * @return List of {@link StreamConsumersInfo} containing information about consumers that belong
     * to the the group
     */
    List<StreamConsumersInfo> xinfoConsumers(String key, String group);

    LCSMatchResult strAlgoLCSStrings(final String strA, final String strB, final StrAlgoLCSParams params);
}
